// Copyright [2020] <unknown>
#include <bits/stdc++.h>
using namespace std;
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define dbg(x...)                             \
    {                                         \
        cerr << "\033[32;1m" << #x << " -> "; \
        err(x);                               \
    }
void err() { cerr << "\033[39;0m" << endl; }
template <typename T, typename... A>
void err(T a, A... x) {
    cerr << a << ' ';
    err(x...);
}
#else
#define dbg(...)
#endif

#define int long long

#define sz(x) ((int)x.size())

typedef long long LL;

const int N = 5050, MOD = 1e9 + 7;

int t, n;

int m;

int f[N], s[N];

int a[N];
int ra[N];
int l[N], r[N], h[N];

inline void update(pair<int, int> &a, pair<int, int> b) {
    if (b.first > a.first)
        a = b;
    else if (b.first == a.first)
        a.second = (a.second + b.second) % MOD;
}

vector<int> cows[N];

bool vis[N];

signed main() {
    // code
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", &s[i]);
        ++r[s[i]];
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%lld%lld", &f[i], &h[i]);

        cows[f[i]].push_back(h[i]);
    }

    for (int i = 1; i <= n; ++i)
        sort(cows[i].begin(), cows[i].end());
    pair<int, int> ans(0, 1);
    for (int i = 1; i <= n; ++i) {
        int b = upper_bound(cows[i].begin(), cows[i].end(), r[i]) - cows[i].begin();
        if (b) {
            ++ans.first;
            ans.second = (LL)ans.second * b % MOD;
        }
    }

    dbg(ans.first, ans.second);
    // static int cnt[N];
    for (int bound = 0; bound <= n; ++bound) {
        --r[s[bound]];
        ++l[s[bound]];
        // dbg(bound, vis[bound]);
        int loc = lower_bound(cows[s[bound]].begin(), cows[s[bound]].end(), l[s[bound]]) - cows[s[bound]].begin();
        // dbg(bound, loc);
        // if (loc < cows[s[bound]].size()) dbg(cows[s[bound]][loc]);
        if (!binary_search(cows[s[bound]].begin(), cows[s[bound]].end(), l[s[bound]]))
            continue;
        pair<int, int> tans(bound > 0, 1);
        // if (bound == n) {
        //     dbg("last", tans.first, tans.second);
        //     update(ans, tans);
        //     break;
        // }
        for (int i = 1; i <= n; ++i) {
            if (s[bound] == i) {
                int b = upper_bound(cows[i].begin(), cows[i].end(), r[i]) - cows[i].begin();
                if (l[s[bound]] <= r[i]) --b;
                dbg(bound, i, l[s[bound]], r[i]);
                if (b) {
                    tans.first += 1;
                    tans.second = (LL)tans.second * b % MOD;
                }
                continue;
            }
            int a = upper_bound(cows[i].begin(), cows[i].end(), l[i]) - cows[i].begin(),
                b = upper_bound(cows[i].begin(), cows[i].end(), r[i]) - cows[i].begin();
            // dbg(bound, i, a, b);
            if (a > b) swap(a, b);
            LL x = 1LL * a * (b - 1) % MOD, y = a + b;
            if (x) {
                tans.first += 2;
                tans.second = (LL)tans.second * x % MOD;
            } else if (y) {
                tans.first += 1;
                tans.second = (LL)tans.second * y % MOD;
            }
        }
        dbg(tans.first, tans.second);
        update(ans, tans);
        dbg(bound, ans.first, ans.second);
    }
    printf("%lld %lld\n", ans.first, ans.second);
    return 0;
}
